#include "PluginSystem.h"
#include <LuaManager.h>
#include <JSONManager.h>
#include <sigar.h>
#include <Windows.h>
#include <WinReg.h>

PluginSystem::PluginSystem()
{
}

PluginSystem::~PluginSystem()
{
}

int PluginSystem::Init()
{
	LuaManager::GetInstance().GetLua().new_usertype<PluginSystem>("PluginSystem",
		sol::constructors<PluginSystem()>(),
		"GetName", &PluginSystem::GetName,
		"GetUser", &PluginSystem::GetUser,
		"GetOS", &PluginSystem::GetOS,
		"GetIP", &PluginSystem::GetIP,
		"GetInfo", &PluginSystem::GetInfo
		);

	return 1;
}

int PluginSystem::Shutdown()
{
	return 1;
}

std::string PluginSystem::GBKToUTF8(const std::string& strGBK)
{
	std::string strOutUTF8 = "";
	WCHAR * str1;
	int n = MultiByteToWideChar(CP_ACP, 0, strGBK.c_str(), -1, NULL, 0);
	str1 = new WCHAR[n];
	MultiByteToWideChar(CP_ACP, 0, strGBK.c_str(), -1, str1, n);
	n = WideCharToMultiByte(CP_UTF8, 0, str1, -1, NULL, 0, NULL, NULL);
	char * str2 = new char[n];
	WideCharToMultiByte(CP_UTF8, 0, str1, -1, str2, n, NULL, NULL);
	strOutUTF8 = str2;
	delete[]str1;
	str1 = 0;
	delete[]str2;
	str2 = 0;
	return strOutUTF8;
}

std::string PluginSystem::GetName()
{
	char szBuffer[500] = { 0 };
	DWORD dwNameLen = sizeof(szBuffer);
	if (!GetComputerName(szBuffer, &dwNameLen)) return NULL;
	std::string strOutUTF8 = GBKToUTF8(szBuffer);
	return strOutUTF8;
}

std::string PluginSystem::GetUser()
{
	char szBuffer[500] = { 0 };
	DWORD dwSize = sizeof(szBuffer);
	if (!GetUserName(szBuffer, &dwSize)) return NULL;
	std::string strOutUTF8 = GBKToUTF8(szBuffer);
	return strOutUTF8;
}

std::string PluginSystem::GetOS()
{
	HKEY hKey;
	LONG nRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_WOW64_64KEY, &hKey);
	if (nRet != ERROR_SUCCESS) return NULL;

	char tmp[500] = { 0 };

	char szProductName[500] = { 0 };
	DWORD dwSize = sizeof(szProductName);
	nRet = RegQueryValueEx(hKey, "ProductName", NULL, NULL, (BYTE *)szProductName, &dwSize);
	if (nRet == ERROR_SUCCESS) sprintf_s(tmp, "%s", szProductName);

	char szCurrentVersion[500] = { 0 };
	dwSize = sizeof(szCurrentVersion);
	nRet = RegQueryValueEx(hKey, "CurrentVersion", NULL, NULL, (BYTE *)szCurrentVersion, &dwSize);
	if (nRet == ERROR_SUCCESS) sprintf_s(tmp, "%s %s", tmp, szCurrentVersion);

	char szReleaseId[500] = { 0 };
	dwSize = sizeof(szReleaseId);
	nRet = RegQueryValueEx(hKey, "ReleaseId", NULL, NULL, (BYTE *)szReleaseId, &dwSize);
	if (nRet == ERROR_SUCCESS) sprintf_s(tmp, "%s.%s", tmp, szReleaseId);

	char szCurrentBuild[500] = { 0 };
	dwSize = sizeof(szCurrentBuild);
	nRet = RegQueryValueEx(hKey, "CurrentBuild", NULL, NULL, (BYTE *)szCurrentBuild, &dwSize);
	if (nRet == ERROR_SUCCESS) sprintf_s(tmp, "%s.%s", tmp, szCurrentBuild);

	RegCloseKey(hKey);

	std::string strOutUTF8 = GBKToUTF8(tmp);
	return strOutUTF8;
}

int getIP(sigar_t *sigar, sigar_uint32_t address, char *addr_str)
{
	char *next = addr_str;
	int n = 0;
	const unsigned char *src =
		(const unsigned char *)&address;

	do {
		unsigned char u = *src++;
		if (u > 99) {
			*next++ = '0' + u / 100;
			u %= 100;
			*next++ = '0' + u / 10;
			u %= 10;
		}
		else if (u > 9) {
			*next++ = '0' + u / 10;
			u %= 10;
		}
		*next++ = '0' + u;
		*next++ = '.';
		n++;
	} while (n < 4);

	*--next = 0;

	return SIGAR_OK;
}

std::string PluginSystem::GetIP()
{
	sigar_t *t = 0;
	sigar_open(&t);

	sigar_net_interface_config_t netconfig;
	sigar_net_interface_config_primary_get(t, &netconfig);

	char tmp[24];
	getIP(t, netconfig.address.addr.in, tmp);

	sigar_close(t);

	std::string strOutUTF8 = GBKToUTF8(tmp);
	return strOutUTF8;
}

std::string PluginSystem::GetInfo()
{
	JSONManager::GetInstance().Create();

	JSONManager::GetInstance().Set("name", GetName().c_str());
	JSONManager::GetInstance().Set("user", GetUser().c_str());
	JSONManager::GetInstance().Set("os", GetOS().c_str());
	JSONManager::GetInstance().Set("address", GetIP().c_str());

	return JSONManager::GetInstance().Get();
}
